/*
 * Copyright 2013 ThirdMotion, Inc.
 *
 *	Licensed under the Apache License, Version 2.0 (the "License");
 *	you may not use this file except in compliance with the License.
 *	You may obtain a copy of the License at
 *
 *		http://www.apache.org/licenses/LICENSE-2.0
 *
 *		Unless required by applicable law or agreed to in writing, software
 *		distributed under the License is distributed on an "AS IS" BASIS,
 *		WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *		See the License for the specific language governing permissions and
 *		limitations under the License.
 */

/**
 * @class strange.framework.impl.SemiBinding
 * 
 * A managed list of values.
 * 
 * @see strange.framework.api.ISemiBinding
 */

using System;
using strange.framework.api;

namespace strange.framework.impl
{
    public class SemiBinding : ISemiBinding
    {
        private object[] objectValue;

        public Enum constraint { get; set; }

        public SemiBinding()
        {
            constraint = BindingConstraintType.ONE;
        }

        #region IManagedList implementation

        public void Add(object o)
        {
            if (objectValue == null || (BindingConstraintType)constraint == BindingConstraintType.ONE)
            {
                objectValue = new object[1];
            }
            else
            {
                if (true)
                {
                    int aa = objectValue.Length;
                    for (int i = 0; i < aa; i++)
                    {
                        object val = objectValue[i];
                        if (val.Equals(o))
                        {
                            return;
                        }
                    }
                }

                object[] tempList = objectValue;
                int len = tempList.Length;
                objectValue = new object[len + 1];
                tempList.CopyTo(objectValue, 0);
            }
            objectValue[objectValue.Length - 1] = o;
        }

        public void Add(object[] list)
        {
            foreach (object item in list)
            {
                Add(item);
            }
        }

        public void Remove(object o)
        {
            if (o.Equals(objectValue) || objectValue == null)
            {
                objectValue = null;
                return;
            }
            int len = objectValue.Length;
            for (int i = 0; i < len; i++)
            {
                object currVal = objectValue[i];
                if (o.Equals(currVal))
                {
                    spliceValueAt(i);
                    return;
                }
            }
        }

        public void Remove(object[] list)
        {
            foreach (object item in list)
            {
                Remove(item);
            }
        }

        public object value
        {
            get
            {
                if (constraint.Equals(BindingConstraintType.ONE))
                {
                    return objectValue?[0];
                }
                return objectValue;
            }
        }

        #endregion

        /// Remove the value at index splicePos
        private void spliceValueAt(int splicePos)
        {
            object[] newList = new object[objectValue.Length - 1];
            int mod = 0;
            int len = objectValue.Length;
            for (int i = 0; i < len; i++)
            {
                if (i == splicePos)
                {
                    mod = -1;
                    continue;
                }
                newList[i + mod] = objectValue[i];
            }
            objectValue = (newList.Length == 0) ? null : newList;
        }
    }
}

